package per.chenxin.scale;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.codec.binary.Base64;

public class HttpUtil {

    final static int INT_BUFFER_SIZE = 8192;

    static public byte[] getBytesFromInputStream(Socket socket, String strURL) throws IOException {

        Pattern pattern = Pattern.compile("[a-zA-z]+://[^\\s]*[:[\\d]{0,5}]{0,1}[/]*.*");
        InputStream input = null;
        BufferedWriter output = null;

        Matcher matcher = pattern.matcher(strURL);
        String host = null;
        int port;
        String path;

        if (matcher.matches()) {
            int intStart = strURL.indexOf("://") + "://".length();
            int intEnd = strURL.indexOf("/", intStart);
            if (intEnd < 0) {
                intEnd = strURL.length();
            }
            host = strURL.substring(intStart, intEnd);
        } else
            return null;

        output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

        output.write("GET " + strURL + " HTTP/1.1\r\n");
        output.write("Host: " + host + "\r\n");
        output.write("Connection: close\r\n");
        output.write("\r\n");
        output.flush();

        return getBytesFromInputStream(socket.getInputStream());

    }

    static public byte[] getBytesFromInputStream(InputStream input) throws IOException {

        StringBuffer sb = new StringBuffer();
        byte[] buffer = new byte[INT_BUFFER_SIZE];
        int intRead = 0;
        int intTotal = 0;
        List<byte[]> listBuffer = new LinkedList<byte[]>();

        while (intRead >= 0) {
            while (input.available() < 0)
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                }

            intRead = input.read(buffer, 0, INT_BUFFER_SIZE);
            if (intRead > 0) {
                sb.append(new String(buffer, 0, intRead));
                intTotal += intRead;
                listBuffer.add(Arrays.copyOfRange(buffer, 0, intRead));
            }
        }

        byte[] bytes = new byte[intTotal];

        for (int i = 0, destPos = 0; i < listBuffer.size(); i++) {
            byte[] byteTemp = listBuffer.get(i);
            System.arraycopy(byteTemp, 0, bytes, destPos, byteTemp.length);
            destPos += byteTemp.length;
        }

        return bytes;

    }

    static public byte[] getMethod(String strUrl) {

        return getMethod(strUrl, null);
    }

    static public byte[] getMethod(String strUrl, Proxy proxy) {

        if (proxy != null && proxy.isUseInternalProxy()) {
            Socket socket = null;
            try {
                socket = new Socket(proxy.internalProxyHost, proxy.internalProxyPort);
                if (proxy.isUseExternalProxy()) {

                }

            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (socket != null) {
                    try {
                        socket.close();
                    } catch (IOException e) {
                    }
                }
            }
        }

        return null;
    }

    static public byte[] getMethod(Socket socket, String strURL) {

        InputStream input = null;
        BufferedWriter output = null;
        Pattern pattern = Pattern.compile("[a-zA-z]+://[^\\s]*[:[\\d]{0,5}]{0,1}[/]*.*");

        try {
            Matcher matcher = pattern.matcher(strURL);
            String host = null;
            int port;
            String path;

            if (matcher.matches()) {
                int intStart = strURL.indexOf("://") + "://".length();
                int intEnd = strURL.indexOf("/", intStart);
                if (intEnd < 0) {
                    intEnd = strURL.length();
                }
                host = strURL.substring(intStart, intEnd);
            } else
                return null;

            input = socket.getInputStream();
            output = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

            output.write("GET " + strURL + " HTTP/1.1\r\n");
            output.write("Host: " + host + "\r\n");
            output.write("Connection: close\r\n");
            output.write("\r\n");
            output.flush();

            StringBuffer sb = new StringBuffer();
            byte[] buffer = new byte[INT_BUFFER_SIZE];
            int intRead = 0;
            int intTotal = 0;
            List<byte[]> listBuffer = new LinkedList<byte[]>();

            while (intRead >= 0) {
                while (input.available() < 0)
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                    }

                intRead = input.read(buffer, 0, INT_BUFFER_SIZE);
                if (intRead > 0) {
                    sb.append(new String(buffer, 0, intRead));
                    intTotal += intRead;
                    listBuffer.add(Arrays.copyOfRange(buffer, 0, intRead));
                }
            }

            byte[] bytes = new byte[intTotal];

            for (int i = 0, destPos = 0; i < listBuffer.size(); i++) {
                byte[] byteTemp = listBuffer.get(i);
                System.arraycopy(byteTemp, 0, bytes, destPos, byteTemp.length);
                destPos += byteTemp.length;
            }

            // try {
            // new WenXueCityParser(bytes).parser();
            // } catch (ParserException e) {
            // e.printStackTrace();
            // }

            // ソケットのクローズ
            input.close();
            output.close();

            return bytes;
        } catch (NumberFormatException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (input != null)
                try {
                    input.close();
                } catch (IOException e) {
                }
            input = null;

            if (output != null)
                try {
                    output.close();
                } catch (IOException e) {
                }
            output = null;

        }
        return null;

    }

    static public Socket getHttpTunnel(Socket connection, String host, int port,
        InetAddress localAddr, int localPort) throws IOException {

        try {
            Writer out = new OutputStreamWriter(connection.getOutputStream(), "ISO-8859-1");
            out.write("CONNECT " + host + ":" + port + " HTTP/1.0\r\n");
            out.write("User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; IDCRL 4.100.313.1; IDCRL-cfg 4.0.5633.0; App msnmsgr.exe, 8.1.178.0, {7108E71A-9926-4FCB-BCC9-9A9D3F32E423})\r\n");
            out.write("Host: " + host + ":" + port + "\r\n");
            out.write("Content-Length: 0\r\n");
            out.write("Connection: Keep-Alive\r\n");
            out.write("Proxy-Connection: Keep-Alive\r\n");
            out.write("Pragma: no-cache\r\n");
            out.write("\r\n");
            out.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                connection.getInputStream(), "ISO-8859-1"));
            String line = null;
            if ((line = in.readLine()) == null
                || !line.matches("^HTTP/[0-9][.][0-9] 2[0-9][0-9] .*")) {
                connection.close();
                throw new IOException(line);
            }
            in.readLine(); // \r\n
        } catch (IOException e) {
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException ioe) {
                    throw ioe;
                }
            }
            throw e;
        }

        return connection;
    }

    static public Socket getHttpTunnel(String host, int port, InetAddress localAddr, int localPort,
        String proxyHost, int proxyPort, String strProxyAuthorization) throws IOException {

        Socket connection = null;
        try {
            if (localAddr == null)
                connection = new Socket(proxyHost, proxyPort);
            else
                connection = new Socket(proxyHost, proxyPort, localAddr, localPort);

            Writer out = new OutputStreamWriter(connection.getOutputStream(), "ISO-8859-1");

            out.write("CONNECT " + host + ":" + port + " HTTP/1.0\r\n");
            out.write("User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; IDCRL 4.100.313.1; IDCRL-cfg 4.0.5633.0; App msnmsgr.exe, 8.1.178.0, {7108E71A-9926-4FCB-BCC9-9A9D3F32E423})\r\n");
            out.write("Host: " + host + ":" + port + "\r\n");
            out.write("Content-Length: 0\r\n");
            out.write("Connection: Keep-Alive\r\n");
            out.write("Proxy-Connection: Keep-Alive\r\n");
            if (strProxyAuthorization != null) {
                out.write("Proxy-Authorization: Basic " + strProxyAuthorization + "\r\n");
            }

            out.write("Pragma: no-cache\r\n");
            out.write("\r\n");
            out.flush();
            BufferedReader in = new BufferedReader(new InputStreamReader(
                connection.getInputStream(), "ISO-8859-1"));
            String line = null;
            if ((line = in.readLine()) == null
                || !line.matches("^HTTP/[0-9][.][0-9] 2[0-9][0-9] .*")) {
                connection.close();
                throw new IOException(line);
            }
            in.readLine(); // \r\n
        } catch (IOException e) {
            if (connection != null) {
                try {
                    connection.close();
                } catch (IOException ioe) {
                    throw ioe;
                }
            }
            throw e;
        }
        return connection;
    }

    static public Socket getHttpTunnel(String host, int port, InetAddress localAddr, int localPort,
        String proxyHost, int proxyPort, String proxyUser, String proxyPassword) throws IOException {

        String strProxyAuthorization = null;
        if (proxyUser != null && proxyPassword != null) {
            strProxyAuthorization = new String(
                Base64.encodeBase64((proxyUser + ":" + proxyPassword).getBytes()));
        }
        System.out.println(strProxyAuthorization);
        return getHttpTunnel(host, port, localAddr, localPort, proxyHost, proxyPort,
            strProxyAuthorization);
    }

}
